/****************************************************************************
** @brief
****************************************************************************/

#include <QDir>
#include <QProcess>
#include <QFileInfo>
#include <QFile>
#include <vector>
#include <iostream>
#include <QByteArray>
#include <QDataStream>
#include <QTextStream>
#include <QString>
#include <QUrl>
#include <fstream>
#include <string>

#include "util.h"
#include "iotUpgradeMain.h"
#include "oiovCallback.h"
#include "oiovMain.h"
#include "chargeMain.h"
#include "status/status.h"
#include "baseConfigure.h"

#include <stdio.h>
#include <stddef.h>
#include <string.h>


#include "../../../iov/ftp/ftplib.h"
#include "../../../iov/ftp/ftplib_config.h"
#include "../../../iov/cjson/cJSON.h"

#include <QDebug>
#define DEBUG_ENABLE

#define OCPP_UPDATE_RTY_MAX 10

struct UpdateInfo IotUpgrade::update_info_;


QFile IotUpgrade::update_file_;
QString IotUpgrade::update_name_;
QByteArray IotUpgrade::update_data_;
cJSON *jsonData;

ECU_staus_t ECU_staus[6];

/* 固件更新开始 */
static int update_start(size_t *size, size_t *crc)
{
    int res = 0;

    IotUpgrade::set_update_size(*size);
    IotUpgrade::set_update_crc(*crc);

    qDebug() << "[IotUpdate]-> start | is_security:" << IotUpgrade::is_security()
             << "size:" << IotUpgrade::update_size() << "crc:" << QString::number(IotUpgrade::update_crc(), 16).toUpper();

    IotUpgrade::update_data_.clear();

    return res;
}
void moveFilesInFolder(const QString& sourceFolder, const QString& destinationFolder)
{
    QDir sourceDir(sourceFolder);
    QDir destDir(destinationFolder);

    if (!sourceDir.exists()) {
        qDebug() << "Source folder does not exist.";
        return;
    }

    if (!destDir.exists()) {
        destDir.mkpath(".");
    }

    QFileInfoList fileInfoList = sourceDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
    for (const QFileInfo& fileInfo : fileInfoList) {
        QString srcFilePath = fileInfo.filePath();
        QString destFilePath = destDir.filePath(fileInfo.fileName());
        if (QFile::rename(srcFilePath, destFilePath)) {
            qDebug() << "Moved file: " << fileInfo.fileName();
        } else {
            qDebug() << "Failed to move file: " << fileInfo.fileName();
        }
    }
}

cJSON *readJsonFile(const QString& filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file:" << filePath;
        return nullptr;
    }

    QByteArray jsonData = file.readAll();
    file.close();

    cJSON *jsonObject = cJSON_Parse(jsonData.constData());
    if (jsonObject == nullptr) {
        const char *error = cJSON_GetErrorPtr();
        qDebug() << "Failed to parse JSON:" << error;
        return nullptr;
    }

    return jsonObject;
}

void moveFile(const QString& sourceFilePath, const QString& destinationDirectory)
{
    QFileInfo fileInfo(sourceFilePath);
    QString destinationFilePath = QDir(destinationDirectory).filePath(fileInfo.fileName());

    if (!QFile::copy(sourceFilePath, destinationFilePath)) {
        qDebug() << "Failed to copy file" << sourceFilePath << "to" << destinationFilePath;
        return;
    }

    qDebug() << "File" << sourceFilePath << "successfully copied to" << destinationFilePath;

    // 如果需要，你可以在这里添加删除原文件的代码
    // QFile::remove(sourceFilePath);
}

QString findFile(const QString& directoryPath, const char *fileName)
{
    QDir directory(directoryPath);
    if (!directory.exists()) {
        qDebug() << "Directory" << directoryPath << "does not exist.";
        return "";
    }

    QStringList files = directory.entryList(QStringList() << fileName, QDir::Files);
    if (files.isEmpty()) {
        qDebug() << "File" << fileName << "not found in directory" << directoryPath;
        return "";
    }

    QString filePath = directory.absoluteFilePath(files.first());
    return filePath;
}

void copyExecutableFilesToOTA(const QString& sourceDir, const QString& targetDir)
{
    // 创建源目录和目标目录的 QDir 对象
    QDir sourceDirectory(sourceDir);
    QDir targetDirectory(targetDir);

    // 获取源目录下的所有文件
    QStringList files = sourceDirectory.entryList(QDir::Files);
    for (const QString& fileName : files) {
        QString filePath = sourceDirectory.filePath(fileName);
        QFileInfo fileInfo(filePath);

        // 检查文件是否为可执行文件
        if (fileInfo.isExecutable()) {
            QString targetFilePath = targetDirectory.filePath("tcu");

            // 复制文件到指定目录并重命名
            if (QFile::copy(filePath, targetFilePath)) {
                qDebug() << "Copied executable file: " << fileInfo.fileName();
            } else {
                qDebug() << "Failed to copy executable file: " << fileInfo.fileName();
            }
        }
    }
}

bool removeDirContents(const QString& dirName)
{
    QDir dir(dirName);
    if (!dir.exists()) {
        return false;
    }

    // 获取目录中的所有文件和子目录
    QStringList entryList = dir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries);
    foreach (QString entry, entryList) {
        QString filePath = dir.absoluteFilePath(entry);
        QFileInfo fileInfo(filePath);

        if (fileInfo.isDir()) {
            // 递归删除子目录
            if (!removeDirContents(filePath)) {
                qDebug() << "Failed to clear contents of subdirectory:" << filePath;
                return false;
            }
            // 删除空的子目录
            if (!dir.rmdir(filePath)) {
                qDebug() << "Failed to remove subdirectory:" << filePath;
                return false;
            }
        } else {
            // 删除文件
            if (!dir.remove(filePath)) {
                qDebug() << "Failed to remove file:" << filePath;
                return false;
            }
        }
    }

    return true;
}
/* 固件更新完成 */
static int update_finish(void)
{
    //  unsigned char hash[32 + 1] = {0}, sign[256 + 1] = {0};
    int result = 0, i = 0;
    //size_t crc = 0, hash_len = 32, sign_len = 0;
    qint64 write_size = 0;
    int  res = 0;
    enum CertificateStatus {
        celient_cer = 1,
        celient_pem,
        celient_key,
    };

    //  IotUpgrade::get_set_Certificate_count() 返回 int 类型，表示不同的证书状态
    CertificateStatus cert_download_status = static_cast<CertificateStatus>(IotUpgrade::get_Certificate_count());

    qDebug() << "[IotUpdate]-> finish";


    //设置对应的文件名
    if (!IotUpgrade::is_security()) {

        //进行数据校验
        QDir currentDir = QDir::current();

        QString dirName = "ota";

        bool have = currentDir.exists(dirName);
        // 删除并重新创建 "ota" 目录
        if (have) {
            qDebug() << "Directory 'ota' exists. Clearing contents...";
            if (removeDirContents(currentDir.absoluteFilePath(dirName))) {
                qDebug() << "Directory content cleared successfully.";
            } else {
                qDebug() << "Failed to clear directory content.";
            }

            if (currentDir.rmdir(currentDir.absoluteFilePath(dirName))) {
                qDebug() << "Directory 'ota' deleted successfully.";
            } else {
                qDebug() << "Failed to delete directory 'ota'. It might still contain files or be in use.";
            }
        }
        // 创建新目录
        if (currentDir.mkdir(dirName)) {
            qDebug() << "Directory" << dirName << "created successfully.";
        }


        IotUpgrade::update_file_.setFileName("ota.tar.gz");
        //打开文件准备将数据写入文件

        IotUpgrade::update_file_.close();
        if (IotUpgrade::update_file_.open(QIODevice::ReadWrite)) {
            write_size = IotUpgrade::update_file_.write(IotUpgrade::update_data_);
            IotUpgrade::set_update_state(kUpdateSuccess); //设置升级状态为升级成功
            qDebug() << "[IotUpdate]-> finish | file open success, write file size is" << write_size;
        } else {
            res = -1;
            IotUpgrade::set_update_state(kUpdateFailed); //设置升级状态为升级失败
            qDebug() << "[IotUpdate]-> finish | file open failed";
        }
        IotUpgrade::update_file_.close();

        QProcess::execute("tar", QStringList() << "-xvf" << "./ota.tar.gz");


        //QDir currentDir = QDir::current();
        QDir destDir("./ota");
        //获取当前目录下的所有子目录
        QStringList subDirs = currentDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
        for (const QString& subDir : subDirs) {
            if (subDir != "ota") {
                QDir subDirPath = currentDir;
                subDirPath.cd(subDir);
                // 获取当前子目录下的所有子目录
                QStringList subSubDirs = subDirPath.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
                for (const QString& subSubDir : subSubDirs) {
                    if (subSubDir == "ECU") {
                        qDebug() << "Found BCU directory in subdirectory " << subDir;
                        // 移动ECU文件夹及其内容到指定目录
                        QString subSubDirPath = subDirPath.filePath(subSubDir);
                        QString targetDir = destDir.filePath(subSubDir);
                        if (QDir().mkpath(targetDir)) {
                            moveFilesInFolder(subSubDirPath, targetDir);
                            qDebug() << "Moved directory: " << subDir;
                        } else {
                            qDebug() << "Failed to create target directory: " << targetDir;
                        }
                        break;
                    }

                }
            }

        }

        QString old_name = "./ota/ECU/thaisenCharging";
        QFile file(old_name);
        QString new_name = "./ota/tcu";

        // 如果目标文件已经存在，先删除它
        if (QFile::exists(new_name)) {
            QFile::remove(new_name);
        }

        if (file.copy(new_name)) {
            qDebug() << "succesed to move APP_OTA: ";
        } else {
            qDebug() << "Failed to move APP_OTA";
        }
        QFile::remove(old_name);

        // 读取JSON文件内容并转换为JSON变量
        cJSON *jsonData = readJsonFile("./ota/ECU/ota_ecu.json");
        if (jsonData == NULL) {
            // 释放JSON变量内存
            cJSON_Delete(jsonData);
            IotUpgrade::set_update_type(kUpdateTypeTCU);
            IotUpgrade::set_is_updateing(1);
            IotUpgrade::set_update_state(kUpdateSuccess);
        } else {
            cJSON *ecuArray = cJSON_GetObjectItem(jsonData, "ecu");
            if (ecuArray != NULL && cJSON_IsArray(ecuArray)) {
                int ecuCount = cJSON_GetArraySize(ecuArray);
                for ( i = 0; i < ecuCount; i++) {
                    cJSON *ecuObj = cJSON_GetArrayItem(ecuArray, i);
                    if (ecuObj != NULL && cJSON_IsObject(ecuObj)) {
                        cJSON *nameItem = cJSON_GetObjectItem(ecuObj, "name");
                        cJSON *versionItem = cJSON_GetObjectItem(ecuObj, "version");
                        cJSON *addressItem = cJSON_GetObjectItem(ecuObj, "address");
                        cJSON *statusItem = cJSON_GetObjectItem(ecuObj, "status");

                        if (nameItem != NULL && cJSON_IsString(nameItem) &&
                                versionItem != NULL && cJSON_IsString(versionItem) &&
                                addressItem != NULL && cJSON_IsString(addressItem) &&
                                statusItem != NULL && cJSON_IsString(statusItem)) {
                            const char *name = nameItem->valuestring;
                            const char *version = versionItem->valuestring;
                            const char *address = addressItem->valuestring;
                            const char *status = statusItem->valuestring;

                            if (strcmp(name, "ccu.bin") == 0) {
                                result = 0;
                                ECU_staus[result].name = kUpdateTypeCCU;
                                ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                                strcpy(ECU_staus[result].version, version);
                                if (strcmp(status, "enabled") == 0) {
                                    ECU_staus[result].is_enabled = 1;
                                } else {
                                    ECU_staus[result].is_enabled = 0;
                                }
                            }
                            if (strcmp(name, "pdu.bin") == 0) {
                                result = 1;
                                ECU_staus[result].name = kUpdateTypeDCU;
                                ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                                strcpy(ECU_staus[result].version, version);
                                if (strcmp(status, "enabled") == 0) {
                                    ECU_staus[result].is_enabled = 1;
                                } else {
                                    ECU_staus[result].is_enabled = 0;
                                }
                            }
                            if (strcmp(name, "pmu.bin") == 0) {
                                result = 2;
                                ECU_staus[result].name = kUpdateTypePMU;
                                ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                                strcpy(ECU_staus[result].version, version);
                                if (strcmp(status, "enabled") == 0) {
                                    ECU_staus[result].is_enabled = 1;
                                } else {
                                    ECU_staus[result].is_enabled = 0;
                                }
                            }

                            if (strcmp(name, "pcm.bin") == 0) {
                                result = 3;
                                ECU_staus[result].name = kUpdateTypeACDC;
                                ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                                strcpy(ECU_staus[result].version, version);
                                if (strcmp(status, "enabled") == 0) {
                                    ECU_staus[result].is_enabled = 1;
                                } else {
                                    ECU_staus[result].is_enabled = 0;
                                }
                            }

                            if (strcmp(name, "dcdc.bin") == 0) {
                                result = 4;
                                ECU_staus[result].name = kUpdateTypeDCDC;
                                ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                                strcpy(ECU_staus[result].version, version);
                                if (strcmp(status, "enabled") == 0) {
                                    ECU_staus[result].is_enabled = 1;
                                } else {
                                    ECU_staus[result].is_enabled = 0;
                                }
                            }
                            if (strcmp(name, "tcu") == 0) {
                                result = 5;
                                ECU_staus[result].name = kUpdateTypeTCU;
                                ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                                strcpy(ECU_staus[result].version, version);
                                if (strcmp(status, "enabled") == 0) {
                                    ECU_staus[result].is_enabled = 1;
                                } else {
                                    ECU_staus[result].is_enabled = 0;
                                }
                            }



                            // 对每个ecu对象进行判断
                            printf("Ecu Object:\n");
                            printf("Name: %s\n", name);
                            printf("Version: %s\n", version);
                            printf("Address: %s\n", address);
                            printf("Status: %s\n", status);
                        }
                    }
                }
            }
            IotUpgrade::set_update_type(kUpdateTypeCCU);
            IotUpgrade::set_is_updateing(1);
            IotUpgrade::set_update_state(kUpdateSuccess);
        }

    } else if (IotUpgrade::is_security()) {

        QDir().mkpath("./cert_client");

        switch (cert_download_status) {
        case celient_key: {
            // 删除原文件（如果存在）
            QFile::remove("./cert_client/celient_MA.key");

            IotUpgrade::update_file_.setFileName("./cert_client/celient-MA.key");
            //打开文件准备将数据写入文件
            if (!IotUpgrade::update_file_.fileName().isEmpty()) {
                qDebug() << "File name set successfully:" << IotUpgrade::update_file_.fileName();
            } else {
                qDebug() << "Failed to set file name.";
            }

            IotUpgrade::update_file_.close();
            if (IotUpgrade::update_file_.open(QIODevice::WriteOnly)) {
                write_size = IotUpgrade::update_file_.write(IotUpgrade::update_data_);
                IotUpgrade::set_update_state(kUpdateSuccess); //设置升级状态为升级成功

                qDebug() << "[IotUpdate]-> finish | file open success, write file size is" << write_size;
            } else {
                res = -1;
                qDebug() << "Failed to open file for writing:" << IotUpgrade::update_file_.errorString();
                IotUpgrade::set_update_state(kUpdateFailed); //设置升级状态为升级失败
            }
            IotUpgrade::update_file_.close();

            break;
        }
        case celient_pem: {

            // 删除原文件（如果存在）
            QFile::remove("./cert_client/celient-MA.pem");
            IotUpgrade::update_file_.setFileName("./cert_client/celient-MA.pem");
            //打开文件准备将数据写入文件
            IotUpgrade::update_file_.close();

            if (IotUpgrade::update_file_.open(QIODevice::ReadWrite)) {
                write_size = IotUpgrade::update_file_.write(IotUpgrade::update_data_);
                IotUpgrade::set_update_state(kUpdateSuccess); //设置升级状态为升级成功
                qDebug() << "[IotUpdate]-> finish | file open success, write file size is" << write_size;
            } else {
                res = -1;
                IotUpgrade::set_update_state(kUpdateFailed); //设置升级状态为升级失败
                qDebug() << "[IotUpdate]-> finish | file open failed";
            }
            IotUpgrade::update_file_.close();
            break;
        }
        case celient_cer: {

            // 删除原文件（如果存在）
            QFile::remove("./cert_client/celient-MA.cer");

            IotUpgrade::update_file_.setFileName("./cert_client/celient-MA.cer");
            //打开文件准备将数据写入文件

            IotUpgrade::update_file_.close();
            if (IotUpgrade::update_file_.open(QIODevice::ReadWrite)) {
                write_size = IotUpgrade::update_file_.write(IotUpgrade::update_data_);
                IotUpgrade::set_update_state(kUpdateSuccess); //设置升级状态为升级成功
                qDebug() << "[IotUpdate]-> finish | file open success, write file size is" << write_size;
            } else {
                res = -1;
                IotUpgrade::set_update_state(kUpdateFailed); //设置升级状态为升级失败
                qDebug() << "[IotUpdate]-> finish | file open failed";
            }
            IotUpgrade::update_file_.close();

//            BaseConfigure::TCU_cert_change();
            break;
        }
        default:
            break;
        }

    }
    return res;
}

static int update_program(const char *buffer, size_t length)
{
    try {
        // 批量追加数据
        IotUpgrade::update_data_.append(buffer, length);

        // 计算进度
        float progress = static_cast<float>(IotUpgrade::update_data_.size()) * 100.0f / IotUpgrade::update_size();
        IotUpgrade::set_update_progress(static_cast<int>(progress * 100)); // 进度保留2位小数

#ifdef DEBUG_ENABLE
        qDebug() << "[IotUpdate]-> progress:" << IotUpgrade::update_data_.size() << "/" << IotUpgrade::update_size()
                 << "(" << IotUpgrade::update_progress() / 100.0f << ")";
#endif

        return 0;
    } catch (const std::exception& e) {
        qDebug() << "Error during update:" << e.what();
        return -1;
    }
}

#if 0
/* 固件更新进行中，编程数据 */
static enum ocpp_error update_program(const char *buffer, size_t length)
{
    //保存接收到的数据

    for (size_t index = 0; index < length; ++index) {
        IotUpgrade::update_data_.append((char)(buffer[index]));
    }
    //计算进度
    float progress = IotUpgrade::update_data_.size() * 100.0f / IotUpgrade::update_size();
    IotUpgrade::set_update_progress(progress * 100); //进度保留2位小数（90.12% -> 9012）

#ifdef DEBUG_ENABLE
    qDebug() << "[IotUpdate]-> progress:" << IotUpgrade::update_data_.size() << "/" << IotUpgrade::update_size()
             << "(" << IotUpgrade::update_progress() / 100.0f << ")";
#endif

    return OCPP_SUCCESS;
}
#endif

IotUpgrade::IotUpgrade(QList<ChargeMain *> *chargelist, QObject *parent) : QThread(parent),
    m_quit(false),
    m_cycle(100)
{
#ifdef DEBUG_ENABLE
    qDebug() << "IotUpgrade::IotUpgrade()";
#endif

    charge_list_ = chargelist;

    //初始化变量

    update_info_.describe = " ";

    //创建文件夹

#ifdef __arm__
    QDir dir;
    QString path = "./ota";
    if (!dir.exists(path)) {
        dir.mkpath(path);
        qDebug() << "[IotUpgrade]-> mkpath update files";
    }
#endif
}

IotUpgrade::~IotUpgrade()
{
#ifdef DEBUG_ENABLE
    qDebug() << "IotUpgrade::~IotUpgrade()";
#endif

    m_quit = true;
    quit(); //线程退出
    wait(); //等待安全退出
}

bool IotUpgrade::check_local_update_path()
{
    QString path = "/mnt/sda1/tcu_update";
    QDir dir(path);
    if (!dir.exists()) {
        return false;
    }
    return true;
}

bool IotUpgrade::check_local_update_file()
{
    QString path = "/mnt/sda1/tcu_update/tcu";
    QDir dir(path);
    if (!dir.exists()) {
        return false;
    }

    return true;
}

QString unescapeHtml(const QString& str)
{
    // QString decodedString = QUrl::fromPercentEncoding(str.toUtf8()); // 解码 URL 编码的字符串
    QString decodedString = str; // 不进行解码，直接使用原始字符串
    decodedString.replace("&amp;", "&"); // 替换 &amp; 为 &
    return decodedString;
}

bool IotUpgrade::process_local_update()
{
    QString name = "./ota/ECU/tcu";
    QFile file(name);
    QString new_name = "./ota/tcu";
    if (file.copy(new_name)) {
        return true;
    } else {
        return false;
    }
}

void IotUpgrade::check_local_update_test()
{
    int result = 0, i = 0;
    QDir currentDir = QDir::current();

    QString dirName = "ota";
    bool have = currentDir.exists(dirName);
    // 删除并重新创建 "ota" 目录
    if (have) {
        qDebug() << "Directory 'ota' exists. Clearing contents...";
        if (removeDirContents(currentDir.absoluteFilePath(dirName))) {
            qDebug() << "Directory content cleared successfully.";
        } else {
            qDebug() << "Failed to clear directory content.";
        }

        if (currentDir.rmdir(currentDir.absoluteFilePath(dirName))) {
            qDebug() << "Directory 'ota' deleted successfully.";
        } else {
            qDebug() << "Failed to delete directory 'ota'. It might still contain files or be in use.";
        }
    }
    // 创建新目录
    if (currentDir.mkdir(dirName)) {
        qDebug() << "Directory" << dirName << "created successfully.";
    }

    QDir destDir("./ota");
    //获取当前目录下的所有子目录
    QStringList subDirs = currentDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
    for (const QString& subDir : subDirs) {
        if (subDir != "ota") {
            QDir subDirPath = currentDir;
            subDirPath.cd(subDir);
            // 获取当前子目录下的所有子目录
            QStringList subSubDirs = subDirPath.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
            for (const QString& subSubDir : subSubDirs) {
                if (subSubDir == "ECU") {
                    qDebug() << "Found BCU directory in subdirectory " << subDir;
                    // 移动ECU文件夹及其内容到指定目录
                    QString subSubDirPath = subDirPath.filePath(subSubDir);
                    QString targetDir = destDir.filePath(subSubDir);
                    if (QDir().mkpath(targetDir)) {
                        moveFilesInFolder(subSubDirPath, targetDir);
                        qDebug() << "Moved directory: " << subDir;
                    } else {
                        qDebug() << "Failed to create target directory: " << targetDir;
                    }
                    break;
                }

            }
        }

    }

    QString name = "./ota/ECU/thaisenCharging";
    QFile file(name);
    QString new_name = "./ota/tcu";
    // 如果目标文件已经存在，先删除它
    if (QFile::exists(new_name)) {
        QFile::remove(new_name);
    }

    if (file.rename(new_name)) {
        qDebug() << "succesed to move APP_OTA: ";
    } else {
        qDebug() << "Failed to move APP_OTA: ";
    }

    // 读取JSON文件内容并转换为JSON变量
    cJSON *jsonData = readJsonFile("./ota/ECU/ota_ecu.json");
    if (jsonData == NULL) {
        // 释放JSON变量内存
        cJSON_Delete(jsonData);
        IotUpgrade::set_update_type(kUpdateTypeTCU);
        IotUpgrade::set_is_updateing(1);
        IotUpgrade::set_update_state(kUpdateSuccess);
    } else {

        cJSON *ecuArray = cJSON_GetObjectItem(jsonData, "ecu");
        if (ecuArray != NULL && cJSON_IsArray(ecuArray)) {
            int ecuCount = cJSON_GetArraySize(ecuArray);
            for ( i = 0; i < ecuCount; i++) {
                cJSON *ecuObj = cJSON_GetArrayItem(ecuArray, i);
                if (ecuObj != NULL && cJSON_IsObject(ecuObj)) {
                    cJSON *nameItem = cJSON_GetObjectItem(ecuObj, "name");
                    cJSON *versionItem = cJSON_GetObjectItem(ecuObj, "version");
                    cJSON *addressItem = cJSON_GetObjectItem(ecuObj, "address");
                    cJSON *statusItem = cJSON_GetObjectItem(ecuObj, "status");

                    if (nameItem != NULL && cJSON_IsString(nameItem) &&
                            versionItem != NULL && cJSON_IsString(versionItem) &&
                            addressItem != NULL && cJSON_IsString(addressItem) &&
                            statusItem != NULL && cJSON_IsString(statusItem)) {

                        const char *name = NULL;
                        const char *version = NULL;
                        const char *address = NULL;
                        const char *status = NULL;

                        name = nameItem->valuestring;
                        version = versionItem->valuestring;
                        address = addressItem->valuestring;
                        status = statusItem->valuestring;

                        // 处理版本号
//                    printf("ECU Name: %s, Version: %s, Address: %s, Status: %s, ECU Version: %s\n",
//                           name, version, address, status, version );

                        if (strcmp(name, "ccu.bin") == 0) {
                            result = 0;
                            ECU_staus[result].name = kUpdateTypeCCU;
                            ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                            strcpy(ECU_staus[result].version, version);
                            if (strcmp(status, "enabled") == 0) {
                                ECU_staus[result].is_enabled = 1;
                            } else {
                                ECU_staus[result].is_enabled = 0;
                            }
                        }
                        if (strcmp(name, "dcu.bin") == 0) {
                            result = 1;
                            ECU_staus[result].name = kUpdateTypeDCU;
                            ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                            strcpy(ECU_staus[result].version, version);
                            if (strcmp(status, "enabled") == 0) {
                                ECU_staus[result].is_enabled = 1;
                            } else {
                                ECU_staus[result].is_enabled = 0;
                            }
                        }
                        if (strcmp(name, "pmu.bin") == 0) {
                            result = 2;
                            ECU_staus[result].name = kUpdateTypePMU;
                            ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                            strcpy(ECU_staus[result].version, version);
                            if (strcmp(status, "enabled") == 0) {
                                ECU_staus[result].is_enabled = 1;
                            } else {
                                ECU_staus[result].is_enabled = 0;
                            }
                        }

                        if (strcmp(name, "acdc.bin") == 0) {
                            result = 3;
                            ECU_staus[result].name = kUpdateTypeACDC;
                            ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                            strcpy(ECU_staus[result].version, version);
                            if (strcmp(status, "enabled") == 0) {
                                ECU_staus[result].is_enabled = 1;
                            } else {
                                ECU_staus[result].is_enabled = 0;
                            }
                        }
                        if (strcmp(name, "dcdc.bin") == 0) {
                            result = 4;
                            ECU_staus[result].name = kUpdateTypeDCDC;
                            ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                            strcpy(ECU_staus[result].version, version);
                            if (strcmp(status, "enabled") == 0) {
                                ECU_staus[result].is_enabled = 1;
                            } else {
                                ECU_staus[result].is_enabled = 0;
                            }
                        }
                        if (strcmp(name, "tcu") == 0) {
                            result = 5;
                            ECU_staus[result].name = kUpdateTypeTCU;
                            ECU_staus[result].address = (uint8_t) strtoul(address, NULL, 10);
                            strcpy(ECU_staus[result].version, version);
                            if (strcmp(status, "enabled") == 0) {
                                ECU_staus[result].is_enabled = 1;
                            } else {
                                ECU_staus[result].is_enabled = 0;
                            }
                        }


                        // 对每个ecu对象进行判断
                        printf("Ecu Object:\n");
                        printf("Name: %s\n", name);
                        printf("Version: %s\n", version);
                        printf("Address: %s\n", address);
                        printf("Status: %s\n", status);

                    }
                }
            }
        }
        // 释放JSON变量内存
        IotUpgrade::set_update_type(kUpdateTypeTCU);
        IotUpgrade::set_update_state(kUpdateSuccess);
    }
}

QString IotUpgrade::replaceHostWithIP(const QString& urlString)
{
    QUrl url(urlString);

    QString domain = url.host();

    QStringList args;

    args << domain;

    QProcess process;
    process.start("nslookup", args);
    process.waitForFinished(-1); // 等待进程完成

    QString output = process.readAllStandardOutput();
    QString error = process.readAllStandardError();

    QString result;
    if (!error.isEmpty()) {
        qWarning() << "Error occurred:" << error;
        result = urlString;
        return result;
    } else {
        bool foundName = false;
        QStringList ipAddresses;
        QStringList lines = output.split("\n", QString::SkipEmptyParts);

        foreach (const QString& line, lines) {
            if (foundName && line.contains("Address") && !line.contains("#")) {

                QString ipAddress = line.section(":", 1).trimmed().section(" ", 0, 0);
                if (!ipAddress.startsWith("192.168.")) {
                    ipAddresses.append(ipAddress);
                    qDebug() << ipAddress;
                }

            }

            // 标记找到了Name行
            if (line.contains("Name")) {
                foundName = true;
            }
        }

        if (!ipAddresses.isEmpty()) {
            QString ip = ipAddresses.first(); // 只取第一个找到的 IP 地址
            int port = url.port();
            if (port == -1) { // 如果原始 URL 没有指定端口号
                port = 443; // 默认使用 HTTPS 端口号
            }
            QString path = url.path();
            result = QString("https://%1:%2%3").arg(ip).arg(port).arg(path);
        } else {
            qWarning() << "No valid IP address found.";
            result = urlString;
        }
    }

    return result;
}



struct _ftp_user_arg_cb {
    char *data;
};

//static netbuf *conn = NULL;
//static netbuf *access = NULL;
//static unsigned int size = 0;
//static unsigned int tsize = 0;
//static char data[FTPLIB_CB_BUFFER] = {0};
//static FtpCallbackOptions opt = {0};
static struct _ftp_user_arg_cb ftp_user_arg_cb = {0};

static int ftp_user_func_cb(netbuf *nControl, fsz_t xfered, void *arg)
{
    static fsz_t size = 0;

    fsz_t count = xfered - size;

    struct _ftp_user_arg_cb *arg_cb = static_cast<struct _ftp_user_arg_cb *>(arg);
//    printf("run ftp callback, xfered is %4d(%5d), data[first] is 0x%02X, data[last] is 0x%02X \n",
//           count, xfered, arg_cb->data[0] & 0xFF, arg_cb->data[count - 1] & 0xFF);
    size = xfered;

    return 1; /* continue next transfer... */
}

#if 1
int IotUpgrade::downloadFileFromFTP(const char *server, const char *user, const char *password, const char *remoteFile)
{
    int result;
    static netbuf *conn = NULL;
    static netbuf *access = NULL;
    unsigned int size;
    char data[1024];
    int tsize = 0;

    FtpCallbackOptions opt;

    FtpInit();

    result = FtpConnect(server, &conn);
    if (!result) {
//        handleError("Failed to connect to FTP server.", conn, access);
        return 0;
    }
    printf("-> Connected to FTP server successfully\n");

    result = FtpLogin(user, password, conn);
    if (!result) {
//        handleError("Failed to login to FTP server.", conn, access);
        return 0;
    }
    printf("-> Logged in to FTP server successfully\n");

    FtpClearCallback(conn);

    result = FtpSize(remoteFile, &size, FTPLIB_IMAGE, conn);
    if (!result) {
//        handleError("Failed to get remote file size.", conn, access);
        return 0;
    }
    printf("-> Remote file size is %d\n", size);

    result = FtpAccess(remoteFile, FTPLIB_FILE_READ, FTPLIB_IMAGE, conn, &access);
    if (!result) {
//        handleError("Failed to access remote file.", conn, access);
        return 0;
    }
    printf("-> Opened remote file successfully\n");


    opt.cbFunc = ftp_user_func_cb; // 这里假设有一个回调函数
    opt.cbArg = &ftp_user_arg_cb;
    opt.idleTime = -1;
    opt.bytesXferred = 1;
    result = FtpSetCallback(&opt, access);
    if (result) {
        printf("-> Callback function established successfully\n");
    }

    while ((result = FtpRead(data, sizeof(data), access)) > 0) {
        // 批量追加数据
        IotUpgrade::update_data_.append(data, sizeof(data));
        // 处理数据，例如写入到本地文件
        msleep(10);
    }

    if (access) {
        FtpClose(access);
    }
    if (conn) {
        FtpQuit(conn);
    }

    printf("-> Connection closed\n");
    return 1;
}
#else

#endif


void IotUpgrade::run()
{
    m_quit = false;

    //实现重试所需要的变量

    int result = 0, rty = 0, restart_count = 0, restart_exe = 3,  ECU_BOOT = 0;

    //检查路径合法性

    QFileInfo fileinfo;
    //初始化升级状态，升级类型和升级进度

    update_info_.state = kUpdateWait;
    update_info_.type = kUpdateTypeInvalid;
    update_info_.progress = 0;

    while (!m_quit) {
        switch (update_info_.state) {
        case kUpdateWait:
            if (update_info_.is_updateing) {
                if (    (Status::kInvalid == charge_list_->at(kGunNumberA)->gun()->state()
                         || Status::kIdle == charge_list_->at(kGunNumberA)->gun()->state()
                         || Status::kFinish == charge_list_->at(kGunNumberA)->gun()->state()
                         || Status::kFault == charge_list_->at(kGunNumberA)->gun()->state()) &&

                        (Status::kInvalid == charge_list_->at(kGunNumberB)->gun()->state()
                         || Status::kIdle == charge_list_->at(kGunNumberB)->gun()->state()
                         || Status::kFinish == charge_list_->at(kGunNumberB)->gun()->state()
                         || Status::kFault == charge_list_->at(kGunNumberB)->gun()->state()) ) {
                    update_info_.progress = 0;
                    update_info_.size = 0;
                    update_info_.crc = 0;
                    update_info_.describe = " ";
                    update_info_.state = kUpdatePre; //进行升级前置处理
                    set_update_type(kUpdateTypeCCU);

                    ECU_BOOT = 0;

                }
                IotUpgrade::update_data_.clear();
            }
            break;
        case kUpdatePre: {
            if (update_info_.is_updateing) {
                QByteArray path((const char *) OiovCallback::ops_active_service_start_update[0].path);
                QString onece_m_update_location = QString(path);

                m_update_req_location = unescapeHtml(QString(onece_m_update_location));
                m_update_req_array = m_update_req_location.toLatin1();
                //QString link_url  = IotUpgrade::replaceHostWithIP(onece_m_update_location);
//                m_update_location  = OiovResMain::resolve_ip_from_host(m_update_req_location);
                //m_update_location   =  unescapeHtml(QString(link_url));
                m_update_location_array = m_update_location.toLatin1();

                time_t _time = time(NULL);
                struct tm *_tm = gmtime(&_time);
                //升级时设备状态切换为不可用
                int gun_i = 0;
                for (  gun_i = 0; gun_i < 12; gun_i++) {

                    OiovCallback::ops_property_charge_data[gun_i].status = OiovCallback::OPS_CHARGINGPILE_STATE_OFFLINE;
                    OiovReqMain::SetDeviceStatusEvent(gun_i);


                }
            }

            qDebug() << "[IotUpdate]-> location:" << m_update_location; //打印远程下载路径

            //检查路径是否有效

            fileinfo.setFile(m_update_location);

            if (fileinfo.isDir()) {
                qDebug() << "[IotUpdate]-> location is dir";
                update_info_.state = kUpdatePollFailed; //设置升级状态为下载失败

            }

            msleep(3 * 1000); //用于上送状态通知
            update_info_.state = kUpdateConnect; //设置升级状态为准备连接
            break;
        }
        case kUpdateConnect: {
//            ocpp_firmware_update_linkkit_free();
//            result = ocpp_firmware_update_linkkit_new((const char *)(m_update_location_array.data()), (const char *)(m_update_req_array.data()));
            if (0 > result) {
                if (rty < OCPP_UPDATE_RTY_MAX) {
                    rty = rty + 1;
                    msleep(1000);
                    qDebug() << "[IotUpdate]-> firmware linkkit failed, retry... ( res:" << result << " rty:" << rty << " )";
                } else {
                    update_info_.state = kUpdatePollFailed; //设置升级状态为下载失败
                }
            } else {
                rty = 0;
                update_info_.state = kUpdatePollData; //连接成功就拉取数据
                //设置固件状态通知 - 下载中

                if (update_info_.is_updateing) {
                    OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x00;
                    OiovReqMain::SetFirmwareStatusEvent(0);
                }

            }
            break;
        }
        case kUpdatePollData: {
//            result = ocpp_firmware_update_poll();
            if (0 > result) {
                qDebug() << "[IotUpdate]-> firmware poll failed, retry connect.";
                update_info_.state = kUpdateConnect; //拉取数据失败重新连接
            } else {
                msleep(10);
                continue; //以尽可能快的速度下载
            }
            break;
        }

        case kUpdatePollFailed:
            //设置固件状态通知 - 下载失败
        {
            if (update_info_.is_updateing) {
                update_info_.state = KUpdatePost; //进行后置处理

                OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x03;
                OiovReqMain::SetFirmwareStatusEvent(0);
            }

            msleep(3 * 1000); //用于上送状态通知
            break;
        }
        case kUpdateSuccess:
            if (update_info_.is_updateing) {
                switch (update_info_.type) {
                case kUpdateTypeTCU:
                    //设置固件状态通知 - 下载完成
                    if (update_info_.is_updateing) {
                        OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x00;
                        OiovReqMain::SetFirmwareStatusEvent(0);
                    }
                    msleep(2 * 1000); //用于上送状态通知
                    //设置固件状态通知 - 安装中
                    if (update_info_.is_updateing) {
                        OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x00;
                        OiovReqMain::SetFirmwareStatusEvent(0);
                    }

                    msleep(3 * 1000); //用于上送状态通知
                    //设置固件状态通知 - 安装完成

                    if (update_info_.is_updateing) {
                        OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x00;
                        OiovReqMain::SetFirmwareStatusEvent(0);
                    }
                    msleep(3 * 1000); //用于上送状态通知

                    update_info_.state = KUpdatePost; //进行后置处理
                    break;
                case kUpdateTypeCCU:
                    update_info_.state = kUpdateInstall; //TCU 的话，还需要将固件下发给 CCU
                    if ((ECU_staus[0].is_enabled + ECU_staus[1].is_enabled + ECU_staus[2].is_enabled + ECU_staus[3].is_enabled + ECU_staus[4].is_enabled) > 0) {
                        //设置固件状态通知 - 下载完成
                        if (update_info_.is_updateing) {
                            OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x00;
                            OiovReqMain::SetFirmwareStatusEvent(0);
                        }
                        msleep(2 * 1000); //用于上送状态通知
                        if (ECU_BOOT == 0) {
                            ECU_BOOT = 1;
                            printf(" root up data can send begain\r\n");
                            emit JL_StartUpdate(ECU_staus[0].is_enabled, ECU_staus[1].is_enabled, ECU_staus[2].is_enabled, ECU_staus[3].is_enabled, ECU_staus[4].is_enabled); //发射信息，开始 CCU 的升级
                        }
                        //设置固件状态通知 - 安装中

                        if (update_info_.is_updateing) {
                            OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x00;
                            OiovReqMain::SetFirmwareStatusEvent(0);
                        }

                    } else {

                    }

                    break;
                default:
                    break;
                }
            }
            break;
        case kUpdateFailed:
            //设置固件状态通知 - 安装失败
            if (update_info_.is_updateing) {
                update_info_.state = KUpdatePost; //进行后置处理
                OiovCallback::ops_active_service_feedback_start_update[0].update_status = 0x03;
                OiovReqMain::SetFirmwareStatusEvent(0);

            }
            msleep(3 * 1000); //用于上送状态通知
            break;
        case kUpdateInstall:
            update_info_.describe = "CCU.INSTALLING";
            break;
        case KUpdatePost:
            if (++restart_count > 1000 / (int)m_cycle) {
                restart_count = 0;
                restart_exe = restart_exe - 1;
            }
            update_info_.describe = "RESTART." + QString::number(restart_exe);
            if (1 > restart_exe) {
                update_info_.is_updateing = false;
                update_info_.is_security = false;
                //emit SystemReboot(); //执行系统重启命令
                QProcess rebootProcess;
                rebootProcess.start("reboot");
                rebootProcess.waitForFinished(-1); // 等待进程结束
            }
            break;
        default:
            break;
        }

        msleep(m_cycle);
    }
}


static char *replace_html_entities(const char *data)
{
    char *result = strdup(data); //对应的内存释放由使用本函数的调用方负责释放
    char *pos = result;

    if (NULL != pos) {
        while ((pos = strstr(pos, "&amp;")) != NULL) {
            *(pos + 0) = '&';
            memmove(pos + 1, pos + 5, strlen(pos + 5) + 1);
        }
    }

    return result;
}
